From 94bbc32d0108e01a541947cb4de1017cabc121b7 Mon Sep 17 00:00:00 2001 From: "iap10@labyrinth.cl.cam.ac.uk" Date: Tue, 15 Apr 2003 15:52:20 +0000 Subject: [PATCH] bitkeeper revision 1.164.1.1 (3e9c2ab4o17BMDDDGKKzLPZtAZk7-g) To allow large initrd's (initial ram disks) for domain0, rearrange the boot code such that the domain 0 module and its optional initrd module are copied to safety before the main boot process begins. At the moment, we're copying it to MAX_DIRECTMAP_ADDRESS, which should be high enough to prevent any nasty overwritting, even on machines with 4GB ram (large frame table) and lots of network/disk devices. We'll find out soon enough if this ever isn't the case ;-) --- xen/arch/i386/boot/boot.S | 44 ++++++++++++++++++++++++++++++++--- xen/common/domain.c | 49 +++++++++++++++++++++++++++++++++++---- xen/common/kernel.c | 18 +++++++++----- xen/include/xeno/sched.h | 3 ++- 4 files changed, 99 insertions(+), 15 deletions(-) diff --git a/xen/arch/i386/boot/boot.S b/xen/arch/i386/boot/boot.S index 1ef335d030..e8993cd663 100644 --- a/xen/arch/i386/boot/boot.S +++ b/xen/arch/i386/boot/boot.S @@ -76,9 +76,9 @@ hal_entry: #endif continue_boot_cpu: - add $__PAGE_OFFSET,%ebx - push %ebx /* Multiboot info struct */ - push %eax /* Multiboot magic value */ + add $__PAGE_OFFSET,%ebx + push %ebx /* Multiboot info struct */ + push %eax /* Multiboot magic value */ /* Initialize BSS (no nasty surprises!) */ mov $__bss_start-__PAGE_OFFSET,%edi @@ -87,6 +87,44 @@ continue_boot_cpu: xor %eax,%eax rep stosb + /* Copy all modules (dom0 + initrd if presetn) to safety, above 48MB */ + mov (%esp),%eax + cmp $0x2BADB002,%eax + jne 2f /* skip if magic no good */ + + sub $__PAGE_OFFSET,%ebx /* turn back into a physaddr */ + + mov 0x14(%ebx),%edi /* mbi->mods_count */ + dec %edi /* count-- */ + + jb 2f /* if num modules was zero !!! */ + + mov 0x18(%ebx),%eax /* mbi->mods_addr */ + + mov (%eax),%ebx /* mod[0]->mod_start */ + + shl $4,%edi /* count*16 */ + add %edi,%eax + + mov 0x4(%eax),%eax /* mod[mod_count-1]->end */ + + mov %eax,%ecx + sub %ebx,%ecx /* length in byte */ + + mov $(MAX_DIRECTMAP_ADDRESS), %edi + add %ecx, %edi /* src + length */ + + shr $2,%ecx /* ecx is length/4 */ + +1: + sub $4,%eax /* eax = src, edi = dst */ + sub $4,%edi + mov (%eax),%ebx + mov %ebx,(%edi) + loop 1b + +2: + /* Initialize low and high mappings of all memory with 4MB pages */ mov $idle0_pg_table-__PAGE_OFFSET,%edi mov $0x1e3,%eax /* PRESENT+RW+A+D+4MB+GLOBAL */ diff --git a/xen/common/domain.c b/xen/common/domain.c index 2102e29ee3..de563ab965 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -362,10 +362,11 @@ static unsigned long alloc_page_from_domain(unsigned long * cur_addr, * userspace dom0 and final setup is being done by final_setup_guestos. */ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params, - char *data_start, unsigned long data_len, char *cmdline) + char *phy_data_start, unsigned long data_len, + char *cmdline, unsigned long initrd_len) { struct list_head *list_ent; - char *src, *dst; + char *src, *vsrc, *dst, *data_start; int i, dom = p->domain; unsigned long phys_l1tab, phys_l2tab; unsigned long cur_address, alloc_address; @@ -382,6 +383,21 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params, /* Sanity! */ if ( p->domain != 0 ) BUG(); + /* This is all a bit grim. We've moved the modules to the "safe" + physical memory region above MAP_DIRECTMAP_ADDRESS (48MB). Later + in this routeine, we're going to copy it down into the region + that's actually been allocated to domain 0. This is highly likely + to be overlapping, so we use a forward copy. + + MAP_DIRECTMAP_ADDRESS should be safe. The worst case is a machine + with 4GB and lots of network/disk cards that allocate loads of + buffers. We'll have to revist this if we ever support PAE (64GB). + + */ + + + data_start = map_domain_mem( (unsigned long) phy_data_start ); + if ( strncmp(data_start, "XenoGues", 8) ) { printk("DOM%d: Invalid guest OS image\n", dom); @@ -532,10 +548,24 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params, __cli(); __write_cr3_counted(pagetable_val(p->mm.pagetable)); - /* Copy the guest OS image. */ - src = (char *)(data_start + 12); + /* Copy the guest OS image. */ + src = (char *)(phy_data_start + 12); + vsrc= (char *)(data_start + 12); /* data_start invalid after first page*/ dst = (char *)virt_load_address; - while ( src < (data_start+data_len) ) *dst++ = *src++; + while ( src < (phy_data_start+data_len) ) + { + *dst++ = *vsrc++; + src++; + + if ( (((unsigned long)src) & (PAGE_SIZE-1)) == 0 ) + { + unmap_domain_mem( vsrc-1 ); + vsrc = map_domain_mem( (unsigned long)src ); + } + } + unmap_domain_mem( vsrc ); + + printk("copy done\n"); /* Set up start info area. */ memset(virt_startinfo_address, 0, sizeof(*virt_startinfo_address)); @@ -545,6 +575,15 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params, virt_startinfo_address->pt_base = virt_load_address + ((p->tot_pages - 1) << PAGE_SHIFT); + if ( initrd_len ) + { + virt_startinfo_address->mod_start = (unsigned long)dst-initrd_len; + virt_startinfo_address->mod_len = initrd_len; + + printk("Initrd len 0x%x, start at 0x%08x\n", + virt_startinfo_address->mod_len, virt_startinfo_address->mod_start); + } + /* Add virtual network interfaces and point to them in startinfo. */ while (params->num_vifs-- > 0) { net_vif = create_net_vif(dom); diff --git a/xen/common/kernel.c b/xen/common/kernel.c index e329980a52..b2316f550d 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -170,7 +170,7 @@ void cmain (unsigned long magic, multiboot_info_t *mbi) printk("Initialised all memory on a %luMB machine\n", max_page >> (20-PAGE_SHIFT)); - init_page_allocator(mod[0].mod_end, MAX_MONITOR_ADDRESS); + init_page_allocator(__pa(&_end), MAX_MONITOR_ADDRESS); /* These things will get done by do_newdomain() for all other tasks. */ current->shared_info = (void *)get_free_page(GFP_KERNEL); @@ -191,15 +191,21 @@ void cmain (unsigned long magic, multiboot_info_t *mbi) new_dom = do_newdomain(0, 0); if ( new_dom == NULL ) panic("Error creating domain 0\n"); + + /* We're going to setup domain0 using the module(s) that we + stashed safely above our MAX_DIRECTMAP_ADDRESS in boot/Boot.S + + The second module, if present, is an initrd ramdisk + */ + if ( setup_guestos(new_dom, &dom0_params, - __va(mod[0].mod_start), - mod[0].mod_end - mod[0].mod_start, - __va(mod[0].string)) + MAX_DIRECTMAP_ADDRESS, + mod[mbi->mods_count-1].mod_end - mod[0].mod_start, __va(mod[0].string), + (mbi->mods_count==2)? + (mod[1].mod_end - mod[1].mod_start):0) != 0 ) panic("Could not set up DOM0 guest OS\n"); - release_bytes_to_allocator(__pa(&_end), mod[0].mod_end); - update_dom_time(new_dom->shared_info); wake_up(new_dom); diff --git a/xen/include/xeno/sched.h b/xen/include/xeno/sched.h index 147f3c40fd..9ca75fb4de 100644 --- a/xen/include/xeno/sched.h +++ b/xen/include/xeno/sched.h @@ -202,7 +202,8 @@ extern struct task_struct first_task_struct; extern struct task_struct *do_newdomain(unsigned int dom_id, unsigned int cpu); extern int setup_guestos( struct task_struct *p, dom0_newdomain_t *params, - char *data_start, unsigned long data_len, char *cmdline); + char *data_start, unsigned long data_len, + char *cmdline, unsigned long initrd_len); extern int final_setup_guestos(struct task_struct *p, dom_meminfo_t *); struct task_struct *find_domain_by_id(unsigned int dom); -- 2.30.2